package com.fangmou.ing.publish.freemarker;

import com.fangmou.ing.util.PathUtils;
import com.fangmou.ing.util.StringUtils;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created : 11-7-27 上午10:44
 * By      : liming
 * freemarker 模版处理引擎
 */
public class FreemarkerEngine {
    /**
     * 模版根目录
     */
    private String baseTemplate;

    /**
     * 解析扩展后的模板
     *
     * @param templatePath
     * @param distPath
     * @param config
     * @param charset
     * @throws java.io.IOException
     * @throws freemarker.template.TemplateException
     * @throws java.lang.IllegalAccessException
     * @return 生成文件路径|模版
     */
    public String process(String templatePath, String distPath, Map config,
                                String charset) throws IOException, TemplateException, IllegalAccessException {
        Configuration configuration = initConfiguration();
        Template template = configuration.getTemplate(templatePath, charset);

        Writer out = new StringWriter();
        template.process(config, out);
        writeToFile(configuration, out.toString(), distPath, charset);
        return distPath + "|" + templatePath;
    }

    private Configuration initConfiguration() throws IOException, IllegalAccessException {
        Configuration configuration = new Configuration();
        configuration.setTemplateLoader(getTemplateLoader());
        DirectiveUtils.exposeRapidMacros(configuration);
        return configuration;
    }

    /**
     * 根据配置参数baseTemplate获取TemplateLoader
     *
     * @return
     * @throws IOException
     * @throws IllegalAccessException
     */
    private TemplateLoader getTemplateLoader() throws IOException, IllegalAccessException {
        TemplateLoader templateLoader;
        if (this.baseTemplate.toLowerCase().startsWith("classpath:"))
            templateLoader = new ClassTemplateLoader(this.getClass(), this.baseTemplate.substring(10));
        else if (this.baseTemplate.toLowerCase().startsWith("context:"))
            templateLoader = new FileTemplateLoader(new File(PathUtils.getWebRoot()+this.baseTemplate.substring(8)));
        else
            templateLoader = new FileTemplateLoader(new File(baseTemplate));
        return templateLoader;
    }

    /**
     * 处理解析结果，并写入文件
     *
     * @param conf
     * @param releaseStr
     * @param fileName
     * @param charset
     * @throws IOException
     */
    private void writeToFile(Configuration conf, String releaseStr, String fileName, String charset) throws IOException {
        Map map = new HashMap();
        String[] attrs = conf.getCustomAttributeNames();
        for (int i = 0; i < attrs.length; i++) {
            if (attrs[i] != null && attrs[i].startsWith(DirectiveUtils.SUPER)) {
                String block = DirectiveUtils.BLOCK + attrs[i].substring(DirectiveUtils.SUPER.length());
                map.put(attrs[i], conf.getCustomAttribute(block));
            }
        }
        if (!map.isEmpty()) {
            Object[] entryArr = map.entrySet().toArray();
            for (int i = 0; i < entryArr.length; i++) {
                //替换当前
                releaseStr = replaceAll(releaseStr, (Map.Entry) entryArr[i]);
                //替换从前，防止后面追加的super被遗漏
                for (int j = 0; j < i; j++) {
                    releaseStr = replaceAll(releaseStr, (Map.Entry) entryArr[j]);
                }
            }
        }

        File page = new File(fileName);
        Writer writer = new OutputStreamWriter(new FileOutputStream(page), charset);
        writer.write(StringUtils.trim(releaseStr));
        writer.flush();
        writer.close();
    }

    /**
     * 字符串替换（纯字符串替换，因String.replaceAll不满足）
     *
     * @param src
     * @param entry
     * @return
     */
    private String replaceAll(String src, Map.Entry entry) {
        if (src == null) {
            return "";
        }
        StringBuffer buff = new StringBuffer();
        String[] ss = src.split((String) entry.getKey());
        buff.append(ss[0]);
        for (int i = 1; i < ss.length; i++) {
            buff.append(entry.getValue());
            buff.append(ss[i]);
        }
        return buff.toString();
    }



    public String getBaseTemplate() {
        return baseTemplate;
    }

    /**
     * 设置模版根目录
     * 默认为文件路径 如 /templates
     * 支持 classpath 路径，如 classpath:/templates
     * 支持 context 路径，如 context:WEB-INF/templates
     *
     * @param baseTemplate
     */
    public void setBaseTemplate(String baseTemplate) {
        this.baseTemplate = baseTemplate;
    }
}
